/*
// my devicetree node
xydnode3399 {
	compatible = "xyd_3399";
	reg = <0xFF76037c 0x4
		0xFF77e000 0x4
		0xFF780004 0x4
		0xFF780000 0x4
	>;
	testprop,mytest;
	test_list_string = "red fish","green fish", "blue fish";
	gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
	interrupt-parent = <&gpio2>;
	interrupts = <7 IRQ_TYPE_EDGE_BOTH>; // 上升沿和下降沿触发
	key-irq-gpio = <&gpio2 7 IRQ_TYPE_EDGE_BOTH>; // GPIO2_A7
	xyd-led3 { //LED3
		gpios = <&gpio2 9 GPIO_ACTIVE_LOW>;  //73
		label = "led3";
	};
};

*/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <dt-bindings/gpio/gpio.h>

static int __init dt_init(void)
{
	int gpio;
	int ret;
	int i;
	u32 regdata[8];
	enum of_gpio_flags flags; //保存有效电平
	struct device_node *np = NULL;
	struct device_node *child_np = NULL;
	struct property *prop = NULL;
	
	//1.通过绝对路径获取设备节点
	np = of_find_node_by_path("/xydnode3399");
	if (np) 
	{
		printk("name=%s\n", np->name);
		printk("full name=%s\n", np->full_name);
	} 
	else 
	{
		printk("of_find_node_by_path fail\n");
		return -EFAULT;
	}

	//2.获取节点下的属性
	prop = of_find_property(np, "compatible", NULL);
	if (prop) 
	{
		printk("name=%s\n", prop->name);
		printk("value=%s\n", (char *)prop->value);
	} 
	else 
	{
		printk("of_find_property fail\n");
		return -EFAULT;
	}

	ret = of_property_read_u32_array(np, "reg", regdata, 8);
	if (!ret) 
	{
		for(i = 0; i < 8; i++) 
			printk("regdata[%d]=0x%x\n", i, regdata[i]);
	}
	else 
	{
		printk("of_property_read_u32_array fail\n");
		return -EFAULT;
	}
	
	prop = of_find_property(np, "testprop,mytest", NULL);
	if (prop) 
		printk("name=%s\n", prop->name);
	else 
	{
		printk("of_find_property fail\n");
		return -EFAULT;
	}

	//获取gpio引脚号 GPIO1_A4
	gpio = of_get_named_gpio_flags(np, "gpios", 0, &flags);
	if (gpio_is_valid(gpio)) {
		printk("gpiono=%d\n", gpio);
		printk("flag==GPIO_ACTIVE_HIGH: %d\n", flags==GPIO_ACTIVE_HIGH);

	} else {
		printk("of_get_named_gpio_flags fail\n");
		return -EFAULT;
	}

	//获取中断引脚号
	gpio = of_get_named_gpio_flags(np, "key-irq-gpio", 0, &flags);
	if (gpio_is_valid(gpio)) 
	{
		printk("key_irq_gpio=%d\n", gpio);
		printk("flag==IRQ_TYPE_EDGE_BOTH: %d\n", flags==IRQ_TYPE_EDGE_BOTH);
	} 
	else 
	{
		printk("of_get_named_gpio_flags fail\n");
		return -EFAULT;
	}
	
	//获取子节点
	//方法1
#if 0
	child_np = of_find_node_by_path("/xydnode3399/xyd-led3");
	if (child_np) {
		printk("name=%s\n", child_np->name);
		printk("full name=%s\n", child_np->full_name);
		gpio = of_get_named_gpio_flags(child_np, "gpios", 0, &flags);
		if (gpio_is_valid(gpio)) {
			printk("gpiono=%d\n", gpio);
			printk("flag==GPIO_ACTIVE_LOW: %d\n", flags==GPIO_ACTIVE_LOW);

		} else {
			printk("of_get_named_gpio_flags fail\n");
			return -EFAULT;
		}

		
	} else {
		printk("of_find_node_by_path fail\n");
		return -EFAULT;
	}

#else
	//方法2
	child_np = of_get_child_by_name(np, "xyd-led3");
	if (child_np) {
		printk("name=%s\n", child_np->name);
		printk("full name=%s\n", child_np->full_name);
		gpio = of_get_named_gpio_flags(child_np, "gpios", 0, &flags);
		if (gpio_is_valid(gpio)) {
			printk("gpiono=%d\n", gpio);
			printk("flag==GPIO_ACTIVE_LOW: %d\n", flags==GPIO_ACTIVE_LOW);

		} else {
			printk("of_get_named_gpio_flags fail\n");
			return -EFAULT;
		}

		
	} else {
		printk("of_get_child_by_name fail\n");
		return -EFAULT;
	}

#endif	
	printk("<kernel> call %s()\n", __func__);
	return 0;
}

static void __exit dt_exit(void)
{
	printk("<kernel> call %s()\n", __func__);
}



module_init(dt_init);
module_exit(dt_exit);
MODULE_LICENSE("GPL");


